package org.daochong.web.filter;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class CSRFTokenFilter implements Filter {
	private String tokenId = "csrf_token";
	private Map<String, String[]> urls;

	public void destroy() {

	}

	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain)
			throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		String[] ar = this.urls.get(request.getMethod());
		boolean find = false;
		if (ar != null) {
			String path = request.getRequestURI();
			for (String url : ar) {
				if (url.length() == 0)
					continue;
				if (url.startsWith("regex:")) {
					url = url.substring(6);
					try {
						Pattern p = Pattern.compile(url);
						find = p.matcher(path).matches();
					} catch (Throwable e) {
						e.printStackTrace();
					}

				} else {
					boolean start = url.charAt(0) == '*';
					boolean end = url.charAt(url.length() - 1) == '*';
					if (start && end) {
						find = (path.indexOf(url.substring(1, url.length() - 1)) >= 0);
					} else if (start && !end) {
						find = path.endsWith(url.substring(1));
					} else if (!start && end) {
						find = path.startsWith(url.substring(0, url.length() - 1));
					} else {
						find = url.equals(path);
					}
				}
			}
		}
		if (find) {
			HttpSession session = request.getSession(true);
			Object value = session.getAttribute(tokenId);
			String code = request.getParameter(tokenId);
			if (code == null) {
				throw new SecurityException("please input the csrf_token");
			}
			if (value == null) {
				throw new SecurityException("csrf_token is null");
			}
			if (!code.equals(value)) {
				throw new SecurityException("csrf_token is not validata");
			}
		}
		filterChain.doFilter(req, resp);
	}

	public void init(FilterConfig config) throws ServletException {
		urls = new LinkedHashMap<String, String[]>();
		String str = config.getInitParameter("GET");
		if (str != null) {
			urls.put("GET", str.split(","));
		}
		str = config.getInitParameter("POST");
		if (str != null) {
			urls.put("POST", str.split(","));
		}
		str = config.getInitParameter("PUT");
		if (str != null) {
			urls.put("PUT", str.split(","));
		}
		str = config.getInitParameter("DELETE");
		if (str != null) {
			urls.put("DELETE", str.split(","));
		}
		str = config.getInitParameter("tokenId");
		if (str != null && str.length() > 0) {
			tokenId = str;
		}
	}

}
